package org.eclipse.mobileapplicationdeveloper.generator;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.mobileapplicationdeveloper.base.command.Consts;
import org.eclipse.mobileapplicationdeveloper.base.util.Rules;
import org.eclipse.mobileapplicationdeveloper.base.util.UtilCommands;

import MobileApplicationDeveloper.model.AppMobile;
import MobileApplicationDeveloper.model.Component;
import MobileApplicationDeveloper.model.View;
import MobileApplicationDeveloper.model.impl.ImageImpl;
import MobileApplicationDeveloper.model.impl.InputImpl;
import MobileApplicationDeveloper.model.impl.LabelImpl;
import MobileApplicationDeveloper.model.impl.ListImpl;

/**
 * Generator of Android platform code.
 * 
 * @author Pablo Oyarzabal.
 * 
 */
public class AndroidGenerator extends AbstractGenerator {

	private static final String BLANK_ZIP = "MyAppAndroid22Froyo.zip";

	/**
	 * Rule for to initialize all files.
	 * 
	 * @param pathDestination
	 * @param appName
	 */
	public void applyInicialitationProjectRule(String pathDestination,
			String appName) {
		UtilCommands.replaceStringInFile(Consts.INITIAL_NAME, appName,
				pathDestination, Consts.ANDROID_MANIFEST_XML);
		UtilCommands.replaceStringInFile(Consts.MY_APP_ANDROID22_FROYO,
				appName, pathDestination, Consts.POINT_PROJECT);
		UtilCommands.replaceStringInFile(Consts.MY_APP_ANDROID22_FROYO,
				appName, pathDestination + "/res/values", Consts.STRINGS_XML);
		// UtilCommands.replaceStringInFile(Consts.INITIAL_NAME, appName,
		// pathDestination + "/bin", Consts.ANDROID_MANIFEST_XML);
		// UtilCommands.replaceStringInFile(Consts.INITIAL_NAME, appName,
		// pathDestination + "/gen/com/example/myappandroid22froyo",
		// "BuildConfig.java");
		// UtilCommands.replaceStringInFile(Consts.INITIAL_NAME, appName,
		// pathDestination + "/gen/com/example/myappandroid22froyo", "R.java");
		// UtilCommands.renameFolder(pathDestination +
		// "/gen/com/example/myappandroid22froyo", pathDestination +
		// "/gen/com/example/" + appName);
		this.makeFolder(pathDestination + "/src/com/example/");
		this.makeFolder(pathDestination + "/res/menu/");
		this.makeFolder(pathDestination + "/src/com/example/" + appName + "/");
	}

	@Override
	public void createAppWith(AppMobile myApp) {

		// create a project with name "name" parameter
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
		View mainView = myApp.getMainView();
		List<View> views = mainView.getNextViews();
		String appName = myApp.getAppName();
		IProject project = root.getProject(appName);
		try {
			project.create(null);
			project.open(null);

			// set the Java nature
			IProjectDescription description = project.getDescription();
			description.setNatureIds(new String[] { JavaCore.NATURE_ID });

			// create the project
			project.setDescription(description, null);
			IJavaProject javaProject = JavaCore.create(project);

			String pathSource = ResourcesPlugin.getPlugin().getStateLocation()
					.toOSString(); // "C:\\tmp\\";

			String pathDestination = project.getLocationURI().getPath();

			UtilCommands.unZipFileCommand(Consts.BLANK_ZIP, pathDestination);
			this.applyInicialitationProjectRule(pathDestination, appName);

			this.createView(mainView, appName, pathDestination);

			IProgressMonitor progress = null;
			javaProject.open(progress);

			// // set the build path
			// IClasspathEntry[] buildPath = {
			// JavaCore.newSourceEntry(project.getFullPath().append("src")),
			// JavaRuntime.getDefaultJREContainerEntry() };
			//
			// javaProject.setRawClasspath(buildPath, project.getFullPath()
			// .append("bin"), null);
			//
			// // create folder by using resources package
			// IFolder folder = project.getFolder("src");
			// folder.create(true, true, null);
			//
			// // Add folder to Java element
			// IPackageFragmentRoot srcFolder = javaProject
			// .getPackageFragmentRoot(folder);
			//
			//
			//
			// // create package fragment
			// IPackageFragment fragment = srcFolder.createPackageFragment(
			// "org.mad.code.activity", true, null);

		} catch (CoreException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void createView(View mainView, String appName,
			String pathDestination) {

		String viewName = mainView.getViewName();
		this.createView(appName, viewName, viewName, viewName, pathDestination);
		this.createComponents(mainView, pathDestination);
	}

	/**
	 * To create components of the view.
	 * @param mainView
	 * @param pathDestination
	 */
	private void createComponents(View mainView, String pathDestination) {

		List<Component> l = mainView.getViewComponents();

		for (Component component : l) {

			if (component.getClass() == ImageImpl.class) {
				try {
					this.createImage(component, mainView, pathDestination);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} else if (component.getClass() == InputImpl.class) {
				try {
					this.createInput(component, mainView, pathDestination);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} else if (component.getClass() == LabelImpl.class) {
				try {
					this.createLabel(component, mainView, pathDestination);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} else if (component.getClass() == ListImpl.class) {
				try {
					this.createList(component, mainView, pathDestination);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} else if (component.getClass() == ListImpl.class) {
				try {
					this.createButton(component, mainView, pathDestination);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * Adding a new List component in the view .
	 * @param component
	 * @param mainView
	 * @param pathDestination
	 * @throws IOException
	 */
	private void createList(Component component, View mainView,
			String pathDestination) throws IOException {

		String activityName = mainView.getViewName() + "View";
		ClassLoader loader = Thread.currentThread().getContextClassLoader();
		InputStream androidActivityXmlTemplateImputStream = loader
				.getResourceAsStream(Consts.ADDING_LAYOUT_EXPANDABLELISTVIEW_XML_TEMPLATE);
		InputStreamReader buttonTemplateInputStreamReader = new InputStreamReader(
				androidActivityXmlTemplateImputStream);

		BufferedReader buttonTemplateActiXmlTemplateBS = new BufferedReader(
				buttonTemplateInputStreamReader);
		String buttonLine = "", oldtext2 = "";
		while ((buttonLine = buttonTemplateActiXmlTemplateBS.readLine()) != null) {
			oldtext2 += buttonLine + "\r\n";
		}
		buttonTemplateActiXmlTemplateBS.close();
		// To replace a line in a file
		String newtext2 = oldtext2.replaceAll("\\$\\{expandableListViewName\\}",
				component.getName().replace(" ", ""));
		// *.
		File file = new File(pathDestination + "/res/layout/",
				activityName.toLowerCase() + ".xml");
		BufferedReader addingButtonXmlBS = new BufferedReader(new FileReader(
				file));

		String line3 = "", oldtext3 = "";
		while ((line3 = addingButtonXmlBS.readLine()) != null) {
			oldtext3 += line3 + "\r\n";
		}
		addingButtonXmlBS.close();

		// To replace a line in a file
		String newtext3 = oldtext3.replaceAll("\\<\\/LinearLayout\\>", newtext2
				+ "\\<\\/LinearLayout\\>");

		// write in the AndroidManifest.xml file
		FileWriter writer2 = new FileWriter(pathDestination + "/res/layout/"
				+ activityName.toLowerCase() + ".xml");

		writer2.write(newtext3);
		writer2.close();
	}

	/**
	 * Adding a new Input component in the view .
	 * 
	 * @param component
	 * @param mainView
	 * @param pathDestination
	 * @throws IOException
	 */
	private void createInput(Component component, View mainView,
			String pathDestination) throws IOException {
		String activityName = mainView.getViewName() + "View";
		ClassLoader loader = Thread.currentThread().getContextClassLoader();
		InputStream androidActivityXmlTemplateImputStream = loader
				.getResourceAsStream(Consts.ADDING_LAYOUT_EDITTEXT_XML_TEMPLATE);
		InputStreamReader buttonTemplateInputStreamReader = new InputStreamReader(
				androidActivityXmlTemplateImputStream);

		BufferedReader buttonTemplateActiXmlTemplateBS = new BufferedReader(
				buttonTemplateInputStreamReader);
		String buttonLine = "", oldtext2 = "";
		while ((buttonLine = buttonTemplateActiXmlTemplateBS.readLine()) != null) {
			oldtext2 += buttonLine + "\r\n";
		}
		buttonTemplateActiXmlTemplateBS.close();
		// To replace a line in a file
		String newtext2 = oldtext2.replaceAll("\\$\\{editTextName\\}",
				component.getName().replace(" ", ""));
		// *.
		File file = new File(pathDestination + "/res/layout/",
				activityName.toLowerCase() + ".xml");
		BufferedReader addingButtonXmlBS = new BufferedReader(new FileReader(
				file));

		String line3 = "", oldtext3 = "";
		while ((line3 = addingButtonXmlBS.readLine()) != null) {
			oldtext3 += line3 + "\r\n";
		}
		addingButtonXmlBS.close();

		// To replace a line in a file
		String newtext3 = oldtext3.replaceAll("\\<\\/LinearLayout\\>", newtext2
				+ "\\<\\/LinearLayout\\>");

		// write in the AndroidManifest.xml file
		FileWriter writer2 = new FileWriter(pathDestination + "/res/layout/"
				+ activityName.toLowerCase() + ".xml");

		writer2.write(newtext3);
		writer2.close();

	}

	/**
	 * Adding a new EditText component in the view.
	 * 
	 * @param component
	 * @param mainView
	 * @param pathDestination
	 * @throws IOException
	 */
	private void createLabel(Component component, View mainView,
			String pathDestination) throws IOException {
		String activityName = mainView.getViewName() + "View";
		ClassLoader loader = Thread.currentThread().getContextClassLoader();
		InputStream androidActivityXmlTemplateImputStream = loader
				.getResourceAsStream(Consts.ADDING_LAYOUT_TEXTVIEW_XML_TEMPLATE);
		InputStreamReader buttonTemplateInputStreamReader = new InputStreamReader(
				androidActivityXmlTemplateImputStream);

		BufferedReader buttonTemplateActiXmlTemplateBS = new BufferedReader(
				buttonTemplateInputStreamReader);
		String buttonLine = "", oldtext2 = "";
		while ((buttonLine = buttonTemplateActiXmlTemplateBS.readLine()) != null) {
			oldtext2 += buttonLine + "\r\n";
		}
		buttonTemplateActiXmlTemplateBS.close();
		// To replace a line in a file
		String newtext2 = oldtext2.replaceAll("\\$\\{textViewName\\}",
				component.getName().replace(" ", ""));
		// *.
		File file = new File(pathDestination + "/res/layout/",
				activityName.toLowerCase() + ".xml");
		BufferedReader addingButtonXmlBS = new BufferedReader(new FileReader(
				file));

		String line3 = "", oldtext3 = "";
		while ((line3 = addingButtonXmlBS.readLine()) != null) {
			oldtext3 += line3 + "\r\n";
		}
		addingButtonXmlBS.close();

		// To replace a line in a file
		String newtext3 = oldtext3.replaceAll("\\<\\/LinearLayout\\>", newtext2
				+ "\\<\\/LinearLayout\\>");

		// write in the AndroidManifest.xml file
		FileWriter writer2 = new FileWriter(pathDestination + "/res/layout/"
				+ activityName.toLowerCase() + ".xml");

		writer2.write(newtext3);
		writer2.close();

	}

	/**
	 * Adding a new Image component in the view.
	 * 
	 * @param component
	 * @param mainView
	 * @param pathDestination
	 * @throws IOException
	 */
	private void createImage(Component component, View mainView,
			String pathDestination) throws IOException {
		String activityName = mainView.getViewName() + "View";
		ClassLoader loader = Thread.currentThread().getContextClassLoader();
		InputStream androidActivityXmlTemplateImputStream = loader
				.getResourceAsStream(Consts.ADDING_LAYOUT_IMAGEVIEW_XML_TEMPLATE);
		InputStreamReader buttonTemplateInputStreamReader = new InputStreamReader(
				androidActivityXmlTemplateImputStream);

		BufferedReader buttonTemplateActiXmlTemplateBS = new BufferedReader(
				buttonTemplateInputStreamReader);
		String buttonLine = "", oldtext2 = "";
		while ((buttonLine = buttonTemplateActiXmlTemplateBS.readLine()) != null) {
			oldtext2 += buttonLine + "\r\n";
		}
		buttonTemplateActiXmlTemplateBS.close();
		// To replace a line in a file
		String newtext2 = oldtext2.replaceAll("\\$\\{imageViewName\\}",
				component.getName().replace(" ", ""));
		// *.
		File file = new File(pathDestination + "/res/layout/",
				activityName.toLowerCase() + ".xml");
		BufferedReader addingButtonXmlBS = new BufferedReader(new FileReader(
				file));

		String line3 = "", oldtext3 = "";
		while ((line3 = addingButtonXmlBS.readLine()) != null) {
			oldtext3 += line3 + "\r\n";
		}
		addingButtonXmlBS.close();

		// To replace a line in a file
		String newtext3 = oldtext3.replaceAll("\\<\\/LinearLayout\\>", newtext2
				+ "\\<\\/LinearLayout\\>");

		// write in the AndroidManifest.xml file
		FileWriter writer2 = new FileWriter(pathDestination + "/res/layout/"
				+ activityName.toLowerCase() + ".xml");

		writer2.write(newtext3);
		writer2.close();

	}

	/**
	 * Adding a new Button component in the view.
	 * 
	 * @param component
	 * @param mainView
	 * @param pathDestination
	 * @throws IOException
	 */
	private void createButton(Component component, View mainView,
			String pathDestination) throws IOException {

		String activityName = mainView.getViewName() + "View";
		ClassLoader loader = Thread.currentThread().getContextClassLoader();
		InputStream androidActivityXmlTemplateImputStream = loader
				.getResourceAsStream(Consts.ADDING_LAYOUT_BOTTON_XML_TEMPLATE);
		InputStreamReader buttonTemplateInputStreamReader = new InputStreamReader(
				androidActivityXmlTemplateImputStream);

		BufferedReader buttonTemplateActiXmlTemplateBS = new BufferedReader(
				buttonTemplateInputStreamReader);
		String buttonLine = "", oldtext2 = "";
		while ((buttonLine = buttonTemplateActiXmlTemplateBS.readLine()) != null) {
			oldtext2 += buttonLine + "\r\n";
		}
		buttonTemplateActiXmlTemplateBS.close();
		// To replace a line in a file
		String newtext2 = oldtext2.replaceAll("\\$\\{buttonName\\}",
				component.getName().replace(" ", ""));
		// *.
		File file = new File(pathDestination + "/res/layout/",
				activityName.toLowerCase() + ".xml");
		BufferedReader addingButtonXmlBS = new BufferedReader(new FileReader(
				file));

		String line3 = "", oldtext3 = "";
		while ((line3 = addingButtonXmlBS.readLine()) != null) {
			oldtext3 += line3 + "\r\n";
		}
		addingButtonXmlBS.close();

		// To replace a line in a file
		String newtext3 = oldtext3.replaceAll("\\<\\/LinearLayout\\>", newtext2
				+ "\\<\\/LinearLayout\\>");

		// write in the AndroidManifest.xml file
		FileWriter writer2 = new FileWriter(pathDestination + "/res/layout/"
				+ activityName.toLowerCase() + ".xml");

		writer2.write(newtext3);
		writer2.close();
	}

	/**
	 * Adding a new view.
	 * 
	 * @param appName
	 * @param activityName
	 * @param layoutActivityName
	 * @param menuActivityName
	 * @param pathDestination
	 */
	public void createView(String appName, String activityName,
			String layoutActivityName, String menuActivityName,
			String pathDestination) {
		// TODO Auto-generated method stub
		try {
			activityName = activityName + "View";
			layoutActivityName = (layoutActivityName + "View").toLowerCase();
			menuActivityName = (menuActivityName + "View").toLowerCase();

			ClassLoader loader = Thread.currentThread().getContextClassLoader();

			// *.java
			InputStream resourceStream = loader
					.getResourceAsStream(Consts.ANDROID_ACTIVITY_JAVA_TEMPLATE);
			InputStreamReader bufferedInputStream = new InputStreamReader(
					resourceStream);

			BufferedReader reader = new BufferedReader(bufferedInputStream);
			String line = "", oldtext = "";
			while ((line = reader.readLine()) != null) {
				oldtext += line + "\r\n";
			}
			reader.close();
			// replace a word in a file
			// String newtext = oldtext.replaceAll("drink", "Love");

			// To replace a line in a file
			String newtext = oldtext.replaceAll("\\$\\{appName\\}", appName);
			newtext = newtext.replaceAll("\\$\\{activityName\\}", activityName);
			newtext = newtext.replaceAll("\\$\\{layoutActivityName\\}",
					layoutActivityName);
			newtext = newtext.replaceAll("\\$\\{menuActivityName\\}",
					menuActivityName);

			FileWriter writer = new FileWriter(pathDestination
					+ "/src/com/example/" + appName + "/" + activityName
					+ ".java");

			writer.write(newtext);
			writer.close();

			// *.AndroidActivity
			InputStream androidActivityXmlTemplateImputStream = loader
					.getResourceAsStream(Consts.ANDROID_ACTIVITY_XML_TEMPLATE);
			InputStreamReader androidActivityXmlTemplateInputStreamReader = new InputStreamReader(
					androidActivityXmlTemplateImputStream);

			BufferedReader andrActiXmlTemplateBS = new BufferedReader(
					androidActivityXmlTemplateInputStreamReader);
			String line2 = "", oldtext2 = "";
			while ((line2 = andrActiXmlTemplateBS.readLine()) != null) {
				oldtext2 += line2 + "\r\n";
			}
			andrActiXmlTemplateBS.close();

			// To replace a line in a file
			String newtext2 = oldtext2.replaceAll("\\$\\{activityName\\}",
					activityName);
			newtext2 = newtext2.replaceAll("\\$\\{titleActivityName\\}",
					"tilte_" + activityName);

			// *.AndroidActivity
			File file = new File(pathDestination + "/"
					+ Consts.ANDROID_MANIFEST_XML);
			BufferedReader andrActiXmlBS = new BufferedReader(new FileReader(
					file));

			String line3 = "", oldtext3 = "";
			while ((line3 = andrActiXmlBS.readLine()) != null) {
				oldtext3 += line3 + "\r\n";
			}
			andrActiXmlBS.close();

			// To replace a line in a file
			String newtext3 = oldtext3.replaceAll("\\<\\/application\\>",
					newtext2 + "\\<\\/application\\>");

			// write in the AndroidManifest.xml file
			FileWriter writer2 = new FileWriter(pathDestination + "/"
					+ Consts.ANDROID_MANIFEST_XML);

			writer2.write(newtext3);
			writer2.close();

			// adding in strings.xml
			UtilCommands
					.replaceStringInFile(
							"\\<\\/resources\\>",
							"    \\<string name\\=\"hello_world\"\\>Hello\u2260\u00A9 world!\\<\\/string\\>\r\n\\<\\/resources\\>",
							pathDestination + "/res/values/",
							Consts.STRINGS_FILE);
			UtilCommands.replaceStringInFile("\\<\\/resources\\>",
					"    \\<string name\\=\"menu_settings\"\\>" + "\u00A9Men"
							+ "\\<\\/string\\>\r\n\\<\\/resources\\>",
					pathDestination + "/res/values/", Consts.STRINGS_FILE);
			UtilCommands.replaceStringInFile("\\<\\/resources\\>",
					"    \\<string name\\=\\\"" + "tilte_" + activityName
							+ "\\\"\\>" + activityName
							+ "\\<\\/string\\>\r\n\\<\\/resources\\>",
					pathDestination + "/res/values/", Consts.STRINGS_FILE);

			// copy layout
			this.copyTemplate(Consts.LAYAOUT_ACTIVITY, pathDestination
					+ "/res/layout/", activityName.toLowerCase() + ".xml");

			// copy layout
			this.copyTemplate(Consts.MENU_ACTIVITY, pathDestination
					+ "/res/menu/", activityName.toLowerCase() + ".xml");

			// copy dimens.xml
			this.copyTemplate(Consts.DIMENS_TEMPLATE, pathDestination
					+ "/res/values/", Consts.DIMENS);

			this.makeFolder(pathDestination + "/res/values-large/");
			// copy dimens.xml large
			this.copyTemplate(Consts.DIMENS_LARGE_TEMPLATE, pathDestination
					+ "/res/values-large/", Consts.DIMENS);

		} catch (IOException ioe) {
			ioe.printStackTrace();
		}

	}

	/**
	 * Rename a folder.
	 * 
	 * @param oldPath
	 * @param newPath
	 */
	public boolean makeFolder(String path) {
		String newUrl = path;
		File file = new File(newUrl);
		// mk dir
		boolean maked = file.mkdirs();
		if (maked) {
			System.out.println("Dir maked to " + newUrl);
		} else {
			System.out.println("Error dir maked " + newUrl);
		}
		return maked;
	}

	/**
	 * Get template and copy at specific path.
	 * 
	 * @param layaoutActivity
	 * @param pathNewProject
	 * @param activityName
	 */
	private void copyTemplate(String layaoutActivity, String pathDestination,
			String activityName) {

		try {
			String file = pathDestination + "/" + activityName;
			ClassLoader loader = Thread.currentThread().getContextClassLoader();
			InputStream resourceStream = loader
					.getResourceAsStream(layaoutActivity);
			InputStreamReader bufferedInputStream = new InputStreamReader(
					resourceStream);

			BufferedReader reader = new BufferedReader(bufferedInputStream);
			String line = "", content = "";
			while ((line = reader.readLine()) != null) {
				content += line + "\r\n";
			}
			reader.close();

			// write in the AndroidManifest.xml file
			FileWriter writer2 = new FileWriter(file);

			writer2.write(content);
			writer2.close();
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
	}

	private void createType(IPackageFragment fragment, String str, String name) {

		String className = name;
		ICompilationUnit cu;
		try {
			cu = fragment.createCompilationUnit(className + ".java", str,
					false, null);

			// create a field
			// IType type = cu.getType(className);
			IType fClass = cu.createType("package " + fragment.getElementName()
					+ ";\n" + "public class " + className + " {\n}\n", null,
					true, null);
			fClass.createField("private String name;", null, true, null);

		} catch (JavaModelException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}
